package cn.omisheep.autt.core.browser;

import cn.omisheep.autt.*;
import cn.omisheep.autt.core.Cookies;
import cn.omisheep.autt.core.Method;
import cn.omisheep.autt.util.SerializeUtil;

import java.util.*;

@SuppressWarnings("all")
public class BrowserConnect implements Connect {

    private Map<String, Map<String, Cookies>> cookies = new HashMap<>();

    int connTimeout = Connect.defaultConnTimeout;
    int readTimeout = Connect.defaultReadTimeout;
    private String context = "";

    @Override
    public GetRequest get(String url) {
        return (GetRequest) generagteRequest(url, Method.GET);
    }

    @Override
    public GetRequest get(String url,
                          Object param) {
        return get(url).param(param);
    }

    @Override
    public PostRequest post(String url) {
        return (PostRequest) generagteRequest(url, Method.POST);
    }

    @Override
    public Connect connTimeout(int connTimeout) {
        this.connTimeout = connTimeout;
        return this;
    }

    @Override
    public Connect readTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
        return this;
    }

    private Request generagteRequest(String url,
                                     Method method) {
        if (url.startsWith("http")) {
            return new BrowserRequest(this, url, method);
        }
        if (context == null || context.equals("")) {
            return new BrowserRequest(this, Autt.getContext() + url, method);
        }
        return new BrowserRequest(this, context + url, method);
    }

    @Override
    public Connect setContext(String context) {
        this.context = context;
        return this;
    }

    @Override
    public List<Cookies> getCookiesListByUri(String domain,
                                             String uri) {
        ArrayList<Cookies> list = new ArrayList<>();
        for (Map.Entry<String, Map<String, Cookies>> entry : cookies.entrySet()) {
            if (!domain.endsWith(entry.getKey())) continue;
            Optional.ofNullable(entry.getValue()).ifPresent(v -> {
                for (Map.Entry<String, Cookies> entry2 : v.entrySet()) {
                    if (uri.startsWith(entry2.getKey())) {
                        list.add(entry2.getValue());
                    }
                }
            });
        }
        return list;
    }

    @Override
    public Cookies getCookiesByDomainAndPath(String domain,
                                             String path) {
        return cookies.get(Objects.requireNonNull(domain, "domain must not null"))
                .get(Objects.requireNonNull(path, "path must not null"));
    }

    @Override
    public String getCookieVal(String domain,
                               String uri,
                               String cookieName) {
        List<Cookies> cookie = getCookiesListByUri(domain, uri);
        for (Cookies c : cookie) {
            Map.Entry<String, String> entry = c.entrySet()
                    .stream()
                    .filter(e -> e.getKey().equals(cookieName))
                    .findFirst()
                    .orElse(null);
            return entry.getValue();
        }
        return null;
    }

    public void setCookie(String domain,
                          String path,
                          Cookies cookie) {
        if (domain.startsWith(".")) {
            domain = domain.substring(1);
        }
        Map<String, Cookies> map = this.cookies.computeIfAbsent(domain, k -> new HashMap<>());
        Cookies              c   = map.get(path);
        if (c == null) {
            map.put(path, cookie);
        } else {
            c.putAll(cookie);
        }
    }

    @Override
    public String saveCookie() {
        return SerializeUtil.serializationObjectByJson(cookies);
    }

    @Override
    public Connect initCookie(String saveCookies) {
        if (saveCookies == null || saveCookies.equals("")) return this;
        cookies = (Map<String, Map<String, Cookies>>) SerializeUtil.deserializationObjectByJson(saveCookies);
        return this;
    }

}
